package cn.rkylin.core;

import cn.rkylin.core.exception.BusinessException;
import cn.rkylin.core.utils.HttpRequester;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

/**
 * 自定义baseDao 增删改查方法
 */
@Service("dataBaseFactory")
public class DataBaseFactoryImpl implements IDataBaseFactory {

	@Autowired
	private HttpRequester httpcilent;
	@Autowired
	private SessionFactory sessionFactory;

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public PageInfo<ApolloRet> findByPage(int pageNo, int pageSize, String index, Map reqMap) throws Exception {
		SqlSession sqlSession = null;
		PageInfo<ApolloRet> result = null;
		String sql = null;
		try {
			sqlSession = getSession(index);
			PageHelper.startPage(pageNo, pageSize, true);
			List list = sqlSession.selectList(index, reqMap);
			result = new PageInfo<ApolloRet>(list);

		} catch (Exception e) {
			throw new BusinessException(e, "-20",
					"pageNo:" + pageNo + ",pageSize:" + pageSize + ",index:" + index + ",params:" + reqMap + ",msg:" + e.getMessage());
		} finally {
			closeSession(sqlSession);
		}
		return result;
	}

	/**
	 * 查询数据,支持 select/enums 两种查询方式(非分页)
	 */
	@SuppressWarnings({ "rawtypes" })
	public <E> List<E> findForList(String index, Map reqMap) throws Exception {
		SqlSession sqlSession = null;
		List<E> result = null;
		MappedStatement ms = null;
		String sql = null;
		try {
			sqlSession = getSession(index);
			ms = sqlSession.getConfiguration().getMappedStatement(index);// mapper节点
			if (SqlCommandType.ENUMS.equals(ms.getSqlCommandType())) {// 节点类型为enum
				result = findByEnums(index, reqMap, ms);// 直接从枚举中获取数据
			} else {
				result = findBySql(index, reqMap, sqlSession);
			}
		} finally {
			closeSession(sqlSession);
		}
		return result;
	}

	/**
	 * 删除操作
	 * 
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	public int delete(String index, Map reqMap) throws Exception {
		String sql = null;
		SqlSession sqlSession = null;
		try {

			sqlSession = getSession(index);
			int count = sqlSession.delete(index, reqMap);
			return count;
		} catch (Exception e) {
			throw new BusinessException(e, "-20", "index:" + index + ",params:" + reqMap+ ",msg:" + e.getMessage());
		} finally {
			closeSession(sqlSession);
		}

	}

	/**
	 * 新增
	 * 
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	public int insert(String index, Map reqMap) throws Exception {
		SqlSession sqlSession = null;
		String sql = null;
		try {
			sqlSession = getSession(index);
			int count = sqlSession.insert(index, reqMap);
			return count;
		} catch (Exception e) {
			throw new BusinessException(e, "-20", "index:" + index + ",params:" + reqMap+ ",msg:" + e.getMessage());
		} finally {
			closeSession(sqlSession);
		}
	}

	/**
	 * 批量新增
	 * 
	 * @param index
	 * @param paramList
	 * @return
	 * @throws Exception
	 */
	public int insertBatch(String index, List paramList) throws Exception {
		SqlSession sqlSession = null;
		String sql = null;
		try {
			sqlSession = getSession(index);
			int count = sqlSession.insert(index, paramList);
			return count;
		} catch (Exception e) {
			throw new BusinessException(e, "-20", "index:" + index + ",params:" + paramList+ ",msg:" + e.getMessage());
		} finally {
			closeSession(sqlSession);
		}
	}

	/**
	 * 更新
	 * 
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	public int update(String index, Map reqMap) throws Exception {
		SqlSession sqlSession = null;
		String sql = null;
		try {
			sqlSession = getSession(index);
			int count = sqlSession.update(index, reqMap);
			return count;
		} catch (Exception e) {
			throw new BusinessException(e, "-20", "index:" + index + ",params:" + reqMap+ ",msg:" + e.getMessage());
		} finally {
			closeSession(sqlSession);
		}
	}

	@SuppressWarnings("rawtypes")
	public int count(String index, Map reqMap) throws Exception {
		SqlSession sqlSession = null;
		try {
			sqlSession = getSession(index);
			Integer count = sqlSession.selectOne(index, reqMap);
			return count;
		} catch (Exception e) {
			throw new BusinessException(e, "-20", "index:" + index + ",params:" + reqMap+ ",msg:" + e.getMessage());
		} finally {
			closeSession(sqlSession);
		}
	}

	/**
	 * 多数据源切换SqlSessionFactory
	 * 
	 * @param index
	 *            sqlID
	 * @return
	 * @throws Exception
	 */
	private SqlSession getSession(String index) throws Exception {
		// index获取对应的conn属性 , 根据conn获取对应的SqlSessionFactory
		// 实现数据源切换
		return sessionFactory.getSessionFactory(ApolloUtil.CONN_MAP.get(index));
	}

	/**
	 * enums类型操作 , 直接从枚举获取数据
	 * 
	 * @param reqMap
	 * @param ms
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private <E> List<E> findByEnums(String index, Map reqMap, MappedStatement ms) throws Exception {
		List result = null;
		BoundSql boundSql = ms.getSqlSource().getBoundSql(reqMap);
		String className = boundSql.getSql().split("@")[0];
		String methodName = boundSql.getSql().split("@")[1];
		Class<?> threadClazz = Class.forName(className);
		Method method = threadClazz.getMethod(methodName, Map.class);
		result = (List<Map>) method.invoke(threadClazz, reqMap);
		return result;
	}

	/**
	 * select类型操作 从对应数据源查询数据
	 * 
	 * @param reqMap
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	private <E> List<E> findBySql(String index, Map reqMap, SqlSession sqlSession) throws Exception {
		List<E> result = null;

		if (index == null)
			return null;
		try {
			result = sqlSession.selectList(index, reqMap);
		} catch (Exception e) {
			throw new BusinessException(e, "-20", "index:" + index + ",params:" + reqMap+ ",msg:" + e.getMessage());
		} finally {
			closeSession(sqlSession);
		}
		return result;
	}

	private void closeSession(SqlSession sqlSession) {
		if (sqlSession != null) {
			// sqlSession.commit();
			// sqlSession.close();
		}
	}

	/**
	 * 泛型分页查询
	 * 
	 * @author wangxiaoyi
	 * @param pageNo
	 * @param pageSize
	 * @param pageStatement
	 * @param paramObj
	 * @return
	 * @throws Exception
	 */
	public <E> PageInfo<E> findPage(int pageNo, int pageSize, String pageStatement, E paramObj) throws Exception {
		SqlSession sqlSession = null;
		PageInfo<E> result = null;
		String sql = null;
		try {
			sqlSession = getSession(pageStatement);
			PageHelper.startPage(pageNo, pageSize, true);
			List<E> list = sqlSession.selectList(pageStatement, paramObj);
			result = new PageInfo<E>(list);
		} catch (Exception e) {
			throw new BusinessException(e, "-20",
					"pageNo:" + pageNo + ",pageSize:" + pageSize + ",index:" + pageStatement + ",params:" + paramObj+ ",msg:" + e.getMessage());
		} finally {
			closeSession(sqlSession);
		}
		return result;
	}

	/**
	 * 按条件全部取得
	 * 
	 * @author wangxiaoyi
	 * @param pageStatement
	 * @param paramObj
	 * @return <E> List<E> 全部结果集取得
	 * @throws Exception
	 */
	public <E> List<E> findList(String pageStatement, String quickSearch) throws Exception {
		SqlSession sqlSession = null;
		List<E> result = null;
		String sql = null;
		try {
			sqlSession = getSession(pageStatement);
			List<E> list = sqlSession.selectList(pageStatement, quickSearch);
			result = list;
		} catch (Exception e) {
			e.printStackTrace();
			throw new BusinessException(e, "-20", ",index:" + pageStatement + ",params:" + quickSearch+ ",msg:" + e.getMessage());
		} finally {
			closeSession(sqlSession);
		}
		return result;
	}

	/**
	 * 按条件全部取得
	 *
	 * @param statement ibatis select name.
	 * @param param ibatis parameter object
	 * @return <E> List<E> 全部结果集取得
	 * @throws Exception any error occurs
	 */
	public <E> List<E> findAllList(String statement, Object param) throws Exception {
		SqlSession sqlSession = null;
		List<E> result = null;
		try {
			sqlSession = getSession(statement);
			return sqlSession.selectList(statement, param);
		} catch (Exception e) {
			throw new BusinessException(e, "-20", ",index:" + statement + ",params:" + param+ ",msg:" + e.getMessage());
		} finally {
			closeSession(sqlSession);
		}
	}

	public int insert(String pageStatement, Object entity) throws Exception {
		int result = 0;
		SqlSession sqlSession = null;
		String sql = null;
		try {
			sqlSession = getSession(pageStatement);
			result = sqlSession.insert(pageStatement, entity);
		} catch (Exception e) {
			throw new BusinessException(e, "-20", pageStatement + "错误"+ ",msg:" + e.getMessage());
		} finally {
			closeSession(sqlSession);
		}
		return result;
	}

	@Override
	public int update(String updateStatement, Object entity) throws Exception {
		int result = 0;
		SqlSession sqlSession = null;
		String sql = null;
		try {
			sqlSession = getSession(updateStatement);
			result = sqlSession.update(updateStatement, entity);
		} catch (Exception e) {
			throw new BusinessException(e, "-20", updateStatement + "错误"+ ",msg:" + e.getMessage());
		} finally {
			closeSession(sqlSession);
		}
		return result;
	}

	@Override
	public int delete(String deleteStatement, Object entity) throws Exception {
		int result = 0;
		SqlSession sqlSession = null;
		String sql = null;
		try {
			sqlSession = getSession(deleteStatement);
			result = sqlSession.delete(deleteStatement, entity);
		} catch (Exception e) {
			throw new BusinessException(e, "-20", deleteStatement + "错误"+ ",msg:" + e.getMessage());
		} finally {
			closeSession(sqlSession);
		}
		return result;
	}

	@Override
	public Object find(String findStatement, Object entity) throws Exception {
		SqlSession sqlSession = null;
		try {
			sqlSession = getSession(findStatement);
			return sqlSession.selectOne(findStatement, entity);
		} catch (Exception e) {
			throw new BusinessException(e, "-20", findStatement + "错误"+ ",msg:" + e.getMessage());
		} finally {
			closeSession(sqlSession);
		}
	}

    @Override
    public <T> T findForObject(String statement, T param) throws BusinessException {
        T returnType = null;
        SqlSession sqlSession = null;
        String sql = null;
        try {
            sqlSession = getSession(statement);
            returnType = sqlSession.selectOne(statement, param);
        } catch (Exception e) {
            throw new BusinessException(e, "-20", statement + "错误"+ ",msg:" + e.getMessage());
        } finally {
            closeSession(sqlSession);
        }
        return returnType;
    }

    /**
     * TODO [简要描述复写方法的内容].
     * @see cn.rkylin.core.IDataBaseFactory#findList(java.lang.String, java.util.Map)
     */
    @Override
    public <E> List<E> findList(String pageStatement, Map<String, Object> params) throws BusinessException {
        SqlSession sqlSession = null;
        List<E> result = null;
        try {
            sqlSession = getSession(pageStatement);
            return sqlSession.selectList(pageStatement, params);
        } catch (Exception e) {
            throw new BusinessException(e, "-20", ",index:" + pageStatement + ",params:" + params+ ",msg:" + e.getMessage());
        } finally {
            closeSession(sqlSession);
        }
    }
}
